package com.atguigu.gmall.product.service;

import org.redisson.client.RedisTimeoutException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.stereotype.Service;

import javax.xml.ws.ServiceMode;
import java.util.Collections;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @author 李旭
 * @date 2021/10/10 9:13
 * @Description:
 */
@Service
public class TestServiceImpl implements TestService {


    @Autowired
    private RedisTemplate redisTemplate;//setnx



    @Override
    public void testLock() {

        String uuid = UUID.randomUUID().toString();
        //分布式锁   0  : false  1: true
        Boolean lock = redisTemplate.opsForValue().setIfAbsent("lock", uuid,3
        , TimeUnit.SECONDS);
        if (lock){
            //上锁成功
            Integer num = (Integer) redisTemplate.opsForValue().get("num");
            num++;
            redisTemplate.opsForValue().set("num",num);
            //解锁
        /*    Object value = redisTemplate.opsForValue().get("lock");
            if(uuid.equals(value)){
                //是自己的锁
                redisTemplate.delete("lock");
                //删除锁 缺少原子性操作
                //Redis 操作具备原子性  set 单线程   原子性操作  get set  set get
            }*/
            //LUA 脚本
            String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return tostring(redis.call('del',KEYS[1])) else return 0 end";
            this.redisTemplate.execute(new DefaultRedisScript<>(script), Collections.singletonList("lock"), uuid);
        }else{
            testLock();
        }
    }

    //  private final Lock lock = new ReentrantLock();

/*    @Override
    public void testLock() {
        lock.lock();
        try {
            Integer num = (Integer) redisTemplate.opsForValue().get("num");
            num++;
            redisTemplate.opsForValue().set("num",num);
        } finally {
            lock.unlock();
        }
    }*/
}
